package com.nettylearning.base.netty.io.bio.tomcat;

import com.nettylearning.base.netty.tomcat.http.GPServlet;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author vince
 * @date 2021/7/24 23:09
 * @Version 1.0
 */
public class GPTomcat {
    private int port = 8080;
    private ServerSocket server;
    private Map<String, GPServlet> servletMapping = new HashMap<String, GPServlet>();

    private Properties webxml = new Properties();

    /**
     * Part-1、初始化阶段，主要完成对web.properties文件的解析
     */
    private void init() {
        // 加载web.xml文件，同时初始化ServletMapping对象
        try {
            String WEB_INF = this.getClass().getResource("/").getPath();
            FileInputStream fis = new FileInputStream(WEB_INF + "web.properties");
            webxml.load(fis);

            for (Object k : webxml.keySet()) {
                String key = k.toString();
                if (key.endsWith(".url")) {
                    String servletName = key.replaceAll("\\.url$", "");
                    String url = webxml.getProperty(key);
                    String className = webxml.getProperty(servletName + ".className");
                    // 单实例，多线程
                    GPServlet gpServlet = (GPServlet) Class.forName(className).newInstance();
                    servletMapping.put(url, gpServlet);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Part-2、服务就绪阶段，完成ServerSocket的准备工作
     */
    public void start() {
        // 1、加载配置文件，初始化servletMapping
        init();

        try {
            server = new ServerSocket(this.port);

            System.out.println("GPTomcat已启动，监听端口为：" + this.port);

            // 2、等待用户请求，用死循环等待用户请求
            while (true) {
                Socket client = server.accept();
                // 3、HTTP请求，发送的数据就是字符串-有规律的字符串(HTTP)
                process(client);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Part-3、接收请求阶段，完成每一次请求的处理，
     *
     * @param client
     * @throws Exception
     */
    private void process(Socket client) throws Exception {
        InputStream inputStream = client.getInputStream();
        OutputStream outputStream = client.getOutputStream();

        // 4. Request(InputStream)/Response(OutputStream)
        GPRequest request = new GPRequest(inputStream);
        GPResponse response = new GPResponse(outputStream);

        // 5.从协议内容中获得URL,把相应的Servlet用反射进行实例化
        String url = request.getUrl();

        if (servletMapping.containsKey(url)) {
            // 6.调用实例化对象的service()方法，执行具体的逻辑doGet()/doPost()方法
            servletMapping.get(url).service(request, response);
        } else {
            response.write("404 - Not Found");
        }

        outputStream.flush();
        outputStream.close();

        inputStream.close();
        client.close();
    }

    public static void main(String[] args) {
        new GPTomcat().start();
    }
}
